
/**
 * @file	sockio.c
 * @brief
 * @author
 * @date
 * @note
 * @see
 * @version $Id$
**/

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>

// 创建监听端口.
int create_listen(char *addr, short port)
{
	struct sockaddr_in sin;
	int sockfd;
	struct  hostent *ht;
	
	memset (&sin, 0, sizeof (sin));

	if(addr != NULL) {
		memset (&sin, 0, sizeof (sin));
		ht = gethostbyname(addr);
		if(ht == NULL) {
			perror ("gethostbyname() error");
			return -1;
		}
		sin.sin_addr.s_addr = (in_addr_t)(ht->h_addr);
	else {
		sin.sin_addr.s_addr = INADDR_ANY;
	}

    sin.sin_port = htons (port);
    sin.sin_family = AF_INET;

    sockfd = socket (PF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
		perror ("socket() error");
		return -1;
    }

	int i=1;
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &i, sizeof(i));

    if (bind (sockfd, (struct sockaddr *) &sin, sizeof (sin)) == -1)
    {
		perror ("bind() error");
		return -1;
    }
    if (listen (sockfd, LISTEN_MAX) == -1)
    {
		perror ("listen() error");
		return -1;
    }

	set_noblock(sockfd);

	return sockfd;
}

// 接收客户端的连接.
int accept_conntion(int sockfd)
{
	struct sockaddr sa;
	socklen_t a;
	int conn;

	conn = accept(sockfd, &sa, &a);
	if(conn == -1) {
		perror("accept() error");
	}

	set_noblock(conn);

	return conn;
}

// 创建一个连接.
int create_connect(char *addr, short port)
{
	struct sockaddr_in sin;
	int sockfd;
	struct  hostent *ht;

	sockfd = socket(AF_INET, SOCK_STREAM, 0);

	memset (&sin, 0, sizeof (sin));
	ht = gethostbyname(addr);
	if(ht == NULL) {
		perror ("gethostbyname() error");
		return -1;
	}
	sin.sin_addr.s_addr = (in_addr_t)(ht->h_addr);
    sin.sin_port = htons (port);
    sin.sin_family = AF_INET;

	if(connect(sockfd, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1) {
		perror ("connect() error");
		return -1;
	}
	
	set_noblock(sockfd);

	return sockfd;
}

int set_noblock(int fd) 
{
	int flag;

	flag = fcntl(sockfd,F_GETFL);

	return fcntl(sockfd, F_SETFL, flag|O_NONBLOCK);
}

// 创建数据报端口.
int create_datagram(char *addr, short port)
{
	struct sockaddr_in sin;
	int sockfd;
	struct  hostent *ht;
	
	memset (&sin, 0, sizeof (sin));

	if(addr != NULL) {
		memset (&sin, 0, sizeof (sin));
		ht = gethostbyname(addr);
		if(ht == NULL) {
			perror ("gethostbyname() error");
			return -1;
		}
		sin.sin_addr.s_addr = (in_addr_t)(ht->h_addr);
	else {
		sin.sin_addr.s_addr = INADDR_ANY;
	}

    sin.sin_port = htons (port);
    sin.sin_family = AF_INET;

    sockfd = socket (PF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
		perror ("socket() error");
		return -1;
    }

	int i=1;
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &i, sizeof(i));

    if (bind (sockfd, (struct sockaddr *) &sin, sizeof (sin)) == -1)
    {
		perror ("bind() error");
		return -1;
    }

	set_noblock(sockfd);

	return sockfd;
}
